package com.yanqu.road.server.manager.activity.condition;

import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.condition.ConditionSyncData;
import com.yanqu.road.entity.activity.condition.ConditionUserData;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.logic.bussiness.activity.CrossConditionBusiness;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.activity.FireWorkProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.YanQuMessageUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class ConditionActivity {

    private ActivityInfo activityInfo;

    private Logger logger = LogManager.getLogger(ConditionActivity.class.getName());

    private Map<Long,Object> lockMap = new ConcurrentHashMap<>();

    //userId conditionType
    private Map<Long, Map<Integer,ConditionUserData>> userDataMap = new ConcurrentHashMap<>();

    private List<ConditionUserData> needInsertUserList = new ArrayList<>();

    private List<ConditionUserData> needUpdateUserList = new ArrayList<>();

    private Map<Integer,List<ConditionSyncData>> needSyncMap = new ConcurrentHashMap<>();

    public ConditionActivity(ActivityInfo activityInfo) {
        this.activityInfo = activityInfo;

        userDataMap = CrossConditionBusiness.getDataMap(activityInfo.getActivityId());
    }

    private Object getLock(long userId){
        if(!lockMap.containsKey(userId)){
            synchronized (lockMap){
                if(!lockMap.containsKey(userId)){
                    lockMap.put(userId,new Object());
                }
            }
        }
        return lockMap.get(userId);
    }

    public void updateData(long serverId, FireWorkProto.CrossUpdateUserConditionReqMsg reqMsg) {
        for(FireWorkProto.CrossUpdateUserConditionMsg msg : reqMsg.getDataList()){
            updateUserData(msg.getActivityId(),msg.getConditionType(),msg.getUserId(),new BigInteger(msg.getValue()),msg.getParam());
        }
    }

    public void updateUserData(int activityId, int conditionType, long userId ,BigInteger value,String param){
        if(!userDataMap.containsKey(userId)){
            synchronized (userDataMap){
                if(!userDataMap.containsKey(userId)){
                    userDataMap.put(userId,new ConcurrentHashMap<>());
                }
            }
        }
        synchronized (getLock(userId)){
            Map<Integer, ConditionUserData> userConditionDataMap = userDataMap.get(userId);
            if(!userConditionDataMap.containsKey(conditionType)){
                ConditionUserData userData = new ConditionUserData();
                userData.setActivityId(activityId);
                userData.setConditionType(conditionType);
                userData.setUserId(userId);
                userData.setValue(value);
                userData.setParam(param);
                userData.setUpdateTime(System.currentTimeMillis());
                userConditionDataMap.put(conditionType,userData);
                addNeedInsertUserData(userData);
            }else{
                ConditionUserData userData = userConditionDataMap.get(conditionType);
                if(userData.getValue().compareTo(value) < 0){
                    userData.setValue(value);
                    userData.setParam(param);
                    userData.setUpdateTime(System.currentTimeMillis());
                    addNeedUpdateUserData(userData);
                }
            }
            ConditionUserData userData = userConditionDataMap.get(conditionType);
            addNeedSyncCondition(userData);
        }
    }

    //吧要更新的加进去
    private void addNeedSyncCondition(ConditionUserData userData){
        synchronized (needSyncMap){
            if(userData.getConditionType() == eGamePlayerEventType.FireWorkHappyValue.getValue()){
                if(!needSyncMap.containsKey(userData.getConditionType())){
                    needSyncMap.put(userData.getConditionType(),new ArrayList<>());
                    ConditionSyncData syncData = new ConditionSyncData();
                    syncData.setActivityId(userData.getActivityId());
                    syncData.setConditionType(userData.getConditionType());
                    syncData.setUserId(0);
                    syncData.setValue(BigInteger.ZERO);
                    syncData.setParam("");
                    needSyncMap.get(userData.getConditionType()).add(syncData);
                }
            }
        }
    }

    private void addNeedInsertUserData(ConditionUserData data){
        synchronized (needInsertUserList){
            if(!needInsertUserList.contains(data)){
                needInsertUserList.add(data);
            }
        }
    }

    private void addNeedUpdateUserData(ConditionUserData data){
        synchronized (needUpdateUserList){
            if(!needUpdateUserList.contains(data)){
                needUpdateUserList.add(data);
            }
        }
    }


    public void timerTask() {
        syncCondition();
    }

    private void syncCondition(){
        List<ConditionSyncData> tmpList = new ArrayList<>();
        if(needSyncMap.size() > 0){
            synchronized (needSyncMap){
                if(needSyncMap.size() > 0){
                    for(List<ConditionSyncData> list : needSyncMap.values()){
                        tmpList.addAll(list);
                    }
                    needSyncMap.clear();
                }
            }
        }

        if(tmpList.size() > 0){
            //serverId
            Map<Long,FireWorkProto.CrossConditionSyncMsg.Builder> syncList = new ConcurrentHashMap<>();
            for(ConditionSyncData syncData : tmpList){
                if(syncData.getConditionType() == eGamePlayerEventType.FireWorkHappyValue.getValue()){
                    FireWorkProto.CrossConditionSyncMsg.Builder syncMsg = FireWorkProto.CrossConditionSyncMsg.newBuilder();
                    syncMsg.setActivityId(activityInfo.getActivityId());
                    BigInteger allValue = BigInteger.ZERO;
                    Map<Long, Map<Integer,ConditionUserData>> tempDataMap = new ConcurrentHashMap<>(userDataMap);
                    for(Map<Integer,ConditionUserData> userDataMap : tempDataMap.values()){
                        if(userDataMap.containsKey(syncData.getConditionType())){
                            allValue = allValue.add(userDataMap.get(syncData.getConditionType()).getValue());
                        }
                    }
                    FireWorkProto.CrossUpdateUserConditionMsg.Builder conditionMsg = FireWorkProto.CrossUpdateUserConditionMsg.newBuilder();
                    conditionMsg.setActivityId(activityInfo.getActivityId());
                    conditionMsg.setConditionType(syncData.getConditionType());
                    conditionMsg.setUserId(0);
                    conditionMsg.setValue(allValue.toString());
                    conditionMsg.setParam("");
                    syncMsg.addData(conditionMsg);
                    //这个类型只会有一条所有区服都一样不用区分
                    for(long serverId : activityInfo.getServerIdList()){
                        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CONDITION_SYNC, syncMsg);
                        MessageHelper.sendPacket(serverId, 0, pbMsg);
                    }
                }
            }


        }
    }


    public void save() {
        List<ConditionUserData> tempInsertList;
        synchronized (needInsertUserList) {
            tempInsertList = new ArrayList<>(needInsertUserList);
            needInsertUserList.clear();
        }
        if (tempInsertList.size() > 0) {
            CrossConditionBusiness.addDataList(tempInsertList);
        }
        List<ConditionUserData> tempUpdateList;
        synchronized (needUpdateUserList) {
            tempUpdateList = new ArrayList<>(needUpdateUserList);
            needUpdateUserList.clear();
        }
        if (tempUpdateList.size() > 0) {
            CrossConditionBusiness.updateDataList(tempUpdateList);
        }

    }

    /**
     * 重新加载配置
     */
    public void reloadConfig() {

    }

    /**
     * 热更
     */
    public void repair() {

    }

    public ActivityInfo getActivityInfo() {
        return activityInfo;
    }

}
